import Icon from "../icon";
import { Button } from "../button";
import transfer from "../directives/transfer";
import { getOffset } from "../utils/element";
import { t } from "../locale";
import { Close } from "kui-icons";

import { withInstall } from '../utils/vue'
const Modal = {
  name: "Modal",
  directives: { transfer },
  props: {
    value: Boolean,
    title: String,
    okText: String,
    cancelText: String,
    top: Number,
    width: Number,
    mask: { type: Boolean, default: true },
    maskClosable: { type: Boolean, default: false },
    maximized: Boolean,
    centered: Boolean,
    draggable: Boolean,
    showClose: { type: Boolean, default: true },
    loading: Boolean,
    footer: String,
    transfer: { type: Boolean, default: true },
    // mode: { type: String, default: 'modal' }
  },
  data() {
    return {
      rendered: false,
      show: this.value,
      showInner: this.value,
      left: "",
      currentTop: this.top,
      isMouseDown: false,
      mousedownIn: false,
      startPos: { x: 0, y: 0 },
      showPoint: { x: 0, y: 0 },
    };
  },
  watch: {
    value(value) {
      this.updateProp(value);
    },
  },
  updated() {
    if (this.show) {
      this.setPos();
    }
  },
  methods: {
    updateProp(visible) {
      if (visible) {
        this.rendered = true;
        this.$nextTick(() => {
          this.show = visible;
          this.showInner = visible;
        });
      } else {
        this.show = false;
        setTimeout(() => {
          this.showInner = false;
        }, 300);
      }
    },
    setPos() {
      if (this.show && this.$refs.modal) {
        let {
          showPoint: { x, y },
        } = this;
        // let { x, y } = showPoint
        let { left, top } = getOffset(this.$refs.modal);
        this.$refs.modal.style["transform-origin"] = `${x - left}px ${y - top}px`;
      }
    },
    ok() {
      this.$emit("ok");
    },
    cancel() {
      this.close();
      this.$emit("cancel");
    },
    close() {
      this.$emit("input", false);
      this.$emit("cancel");
      this.$emit("close");
    },
    clickMaskToClose(e) {
      if (!this.loading && this.maskClosable && !this.$refs.modal.contains(e.target) && !this.mousedownIn) {
        this.close();
      }
    },
    mousemove(e) {
      if (this.isMouseDown && this.draggable) {
        let { x, y } = this.startPos;
        this.left += e.clientX - x;
        this.currentTop = this.currentTop || 100;
        this.currentTop += e.clientY - y;
        this.startPos = { x: e.clientX, y: e.clientY };
        this.setPos();
        e.preventDefault();
      }
    },
    mouseup() {
      this.isMouseDown = false;
      document.removeEventListener("mousemove", this.mousemove);
      document.removeEventListener("mouseup", this.mouseup);
    },
    mousedown(e) {
      if (!this.show) {
        this.showPoint = { x: e.clientX, y: e.clientY };
      }
      if (e.button == 0 && this.draggable === true && this.$refs.hRef && this.$refs.hRef.contains(e.target)) {
        this.isMouseDown = true;
        this.startPos = { x: e.clientX, y: e.clientY };
        this.mousemove(e);
        document.addEventListener("mousemove", this.mousemove);
        document.addEventListener("mouseup", this.mouseup);
      }

      this.mousedownIn = this.show && this.$refs.modal && this.$refs.modal.contains(e.target);
    },
  },
  beforeDestroy() {
    typeof window !== "undefined" && document.removeEventListener("mousedown", this.mousedown);
    // this.resetBodyStyle(false)
  },

  mounted() {
    if (typeof window !== "undefined") {
      document.addEventListener("mousedown", this.mousedown);

      if (this.draggable) {
        this.left = (document.body.offsetWidth - (this.width || 520)) / 2;
      }
      if (this.value) {
        this.$nextTick(() => {
          this.updateProp(true);
        });
      }
    }
  },
  render() {
    let { $slots, show, showInner, draggable, transfer } = this;

    //mask
    let maskNode = null;
    if (this.mask) {
      maskNode = (
        <transition name="k-modal-fade">
          <div class="k-modal-mask" v-show={show} />
        </transition>
      );
    }
    let okText = this.okText || t("k.modal.ok");
    let cancelText = this.cancelText || t("k.modal.cancel");
    //content
    let contentNode = $slots.content;
    if (!contentNode) {
      const contents = [];
      this.showClose &&
        contents.push(
          <span class="k-modal-close" onClick={this.close}>
            <Icon type={Close} strokeWidth={50} />
          </span>
        );
      this.title !== null &&
        contents.push(
          <div class="k-modal-header" ref="hRef">
            <div class="k-modal-header-inner">{this.title}</div>
          </div>
        );
      contents.push(<div class="k-modal-body">{$slots.default}</div>);

      //footer
      if (this.footer !== null) {
        let footer = $slots.footer;
        if (!footer) {
          footer = [
            <Button onClick={this.cancel}>{cancelText}</Button>,
            <Button onClick={this.ok} type="primary" loading={this.loading}>
              {okText}
            </Button>,
          ];
        }
        const footerNode = footer ? <div class="k-modal-footer">{footer}</div> : null;

        contents.push(footerNode);
      }
      contentNode = <div class="k-modal-content">{contents}</div>;
    }

    const style = {
      width: `${this.width}px`,
      top: `${this.currentTop}px`,
      left: `${this.left}px`,
    };
    const classes = [
      "k-modal",
      {
        "k-modal-draggable": draggable,
        "k-modal-maximized": this.maximized,
        "k-modal-centered": this.centered,
        "k-modal-has-footer": this.footer !== null,
      },
    ];
    return this.rendered ? (
      <div class={classes} v-transfer={transfer}>
        {maskNode}
        <div class="k-modal-wrap" v-show={showInner} onClick={this.clickMaskToClose}>
          <transition name="k-modal-zoom">
            <div class="k-modal-inner" ref="modal" v-show={show} style={style}>
              {contentNode}
            </div>
          </transition>
        </div>
      </div>
    ) : null;
  },
};

export default withInstall(Modal);